package com.ysxsoft.common_base.view.custom.date;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.collection.ArraySet;
import androidx.viewpager.widget.PagerAdapter;
import androidx.viewpager.widget.ViewPager;

import com.ysxsoft.common_base.R;
import com.ysxsoft.common_base.view.widgets.NoScrollViewPager;

import java.util.Calendar;
import java.util.HashMap;


/**
 * 日历视图组
 */
public class ECalendarView extends FrameLayout {

	private ArraySet<ECalendar> destroyViews = new ArraySet<>();
	private ArraySet<ECalendar> viewSet = new ArraySet<>();
	private int selectYear, selectMonth, selectDay, selectWeek;
	private HashMap<String, Boolean> signRecords;
	private HashMap<String, CalendarBean> datas;
	private int PAGER_SIZE = 1200;
	private Calendar calendar;
	private NoScrollViewPager pager;
	private Config config;
	private Context context;

	public ECalendarView(Context context) {
		super(context);
		this.context = context;
		init(null, 0);
	}

	public ECalendarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		init(attrs, 0);
	}

	public ECalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		this.context = context;
		init(attrs, defStyleAttr);
	}

	private void init(AttributeSet attrs, int def) {
		config = new Config();
		//获取日历的UI配置
		TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.ECalendarView, def, 0);
		config.weekHeight = array.getDimension(R.styleable.ECalendarView_weekHeight, dip2px(30));
		config.weekBackgroundColor = array.getColor(R.styleable.ECalendarView_weekBackgroundColor, Color.WHITE);
		config.weekTextColor = array.getColor(R.styleable.ECalendarView_weekTextColor, Color.GRAY);
		config.weekTextSize = array.getDimension(R.styleable.ECalendarView_weekTextSize, sp2px(14));
		config.calendarTextColor = array.getColor(R.styleable.ECalendarView_calendarTextColor, Color.BLACK);
		config.calendarTextSize = array.getDimension(R.styleable.ECalendarView_calendarTextSize, sp2px(14));
		config.isShowOtherMonth = array.getBoolean(R.styleable.ECalendarView_isShowOtherMonth, false);
		if (config.isShowOtherMonth) {
			config.otherMonthTextColor = array.getColor(R.styleable.ECalendarView_otherMonthTextColor, Color.LTGRAY);
		}
		config.isShowLunar = array.getBoolean(R.styleable.ECalendarView_isShowLunar, false);
		if (config.isShowLunar) {
			config.lunarTextColor = array.getColor(R.styleable.ECalendarView_lunarTextColor, Color.LTGRAY);
			config.lunarTextSize = array.getDimension(R.styleable.ECalendarView_lunarTextSize, sp2px(11));
		}
		config.todayTextColor = array.getColor(R.styleable.ECalendarView_todayTextColor, Color.BLUE);
		config.selectColor = array.getColor(R.styleable.ECalendarView_selectColor, Color.BLUE);
		config.selectTextColor = array.getColor(R.styleable.ECalendarView_selectTextColor, Color.WHITE);
		config.signIconSuccessId = array.getResourceId(R.styleable.ECalendarView_signIconSuccessId, 0);
		config.noteResouceId = array.getResourceId(R.styleable.ECalendarView_noteResourceId, 0);
		config.moneyResouceId = array.getResourceId(R.styleable.ECalendarView_moneyResourceId, 0);
		config.signIconErrorId = array.getResourceId(R.styleable.ECalendarView_signIconErrorId, 0);
		if (config.signIconSuccessId != 0) {
			config.signIconSize = array.getDimension(R.styleable.ECalendarView_signIconSize, dip2px(12));
		}
		config.noteResouceSize = array.getDimension(R.styleable.ECalendarView_noteIconSize, dip2px(12));
		config.signTextColor = array.getColor(R.styleable.ECalendarView_signTextColor, Color.parseColor("#BA7436"));
		config.limitFutureMonth = array.getBoolean(R.styleable.ECalendarView_limitFutureMonth, false);
		array.recycle();
		initPager();
	}

	private float sp2px(float spValue) {
		float fontScale = getContext().getResources().getDisplayMetrics().scaledDensity;
		return spValue * fontScale + 0.5f;
	}

	private int dip2px(float dipValue) {
		final float scale = Resources.getSystem().getDisplayMetrics().density;
		return (int) (dipValue * scale + 0.5f);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		int height = MeasureSpec.getSize(heightMeasureSpec);
		int hMode = MeasureSpec.getMode(heightMeasureSpec);
		height = hMode == MeasureSpec.EXACTLY ? height : dip2px(220);
		setMeasuredDimension(widthMeasureSpec, height);
	}

	private void initPager() {
		//不能滑动
		pager = new NoScrollViewPager(getContext());
		addView(pager);
		pager.setOffscreenPageLimit(1);
		pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
			@Override
			public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
			}

			@Override
			public void onPageSelected(int position) {
				if (listener == null){
					return;
				}
				position -= 1;
				int year = 1970 + position / 12;
				int month = position % 12;
				listener.change(year, month + 1);
			}

			@Override
			public void onPageScrollStateChanged(int state) {
			}
		});

		//选择当前日期
		calendar = Calendar.getInstance();
		selectYear = calendar.get(Calendar.YEAR);
		selectMonth = calendar.get(Calendar.MONTH);
		selectDay = calendar.get(Calendar.DAY_OF_MONTH);
		selectWeek = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		int currentPosition = getPosition(selectYear, selectMonth);
		if (config.limitFutureMonth){
			PAGER_SIZE = currentPosition + 1;
		}
		pager.setAdapter(new CVAdapter());
		pager.setCurrentItem(currentPosition, false);
	}

	private int getPosition(int year, int month) {
		return (year - 1970) * 12 + month + 1;
	}

	private class CVAdapter extends PagerAdapter {
		@Override
		public int getCount() {
			return PAGER_SIZE;
		}

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == object;
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			ECalendar calendarView = getContent(position);
			container.addView(calendarView);
			return calendarView;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			destroyViews.add((ECalendar) object);
			container.removeView((View) object);
		}
	}

	private ECalendar getContent(int position) {
		ECalendar calendarView;
		if (destroyViews.size() != 0) {
			calendarView = destroyViews.valueAt(0);
			destroyViews.remove(calendarView);
		} else {
			calendarView = new ECalendar(getContext());
			calendarView.init(config);
			calendarView.setDateSelectListener(new ECalendar.DateSelectListener() {
				@Override
				public void dateSelect(int year, int month, int day, int week) {
					selectYear = year;
					selectMonth = month;
					selectDay = day;
					for (ECalendar view : viewSet) {
						view.initSelect(selectYear, selectMonth, selectDay);
					}
					if (listener != null) {
						listener.select(year, month + 1, day, week == 0 ? 7 : week);
					}
				}
			});
			viewSet.add(calendarView);
		}
		calendarView.setSignRecords(signRecords);
		calendarView.setDatas(datas);
		calendarView.selectDate(position);
		calendarView.setTag(position);
		return calendarView;
	}

	static class Config {
		float weekHeight;
		float weekTextSize;
		int weekBackgroundColor;
		int weekTextColor;
		float calendarTextSize;
		int calendarTextColor;
		boolean isShowOtherMonth;
		int otherMonthTextColor;
		boolean isShowLunar;
		int lunarTextColor;
		float lunarTextSize;
		int todayTextColor;
		int selectColor;
		int selectTextColor;
		int signIconSuccessId;
		int signIconErrorId;
		float signIconSize;
		int signTextColor;
		boolean limitFutureMonth;
		//add
		int noteResouceId;
		int moneyResouceId;
		int noteColor;
		float noteResouceSize;
		float orderTextSize;
		int orderTextColor;
		String orderNum;
		String orderMoney;
	}

	/*---------------------------------------对外方法-----------------------------------*/
	public interface SelectListener {
		void change(int year, int month);

		void select(int year, int month, int day, int week);
	}

	private SelectListener listener;

	public void setSelectListener(SelectListener listener) {
		this.listener = listener;
		listener.change(selectYear, selectMonth + 1);
		selectWeek = selectWeek == 0 ? 7 : selectWeek;
		listener.select(selectYear, selectMonth + 1, selectDay, selectWeek);
	}

	public void selectDate(int year, int month, int day) {
		if (listener == null || year < 1970 || month < 1 || month > 12 || day < 1 || day > 31)
		{
			return;
		}
		month -= 1;
		calendar.set(year, month, day);
		int yearTemp = calendar.get(Calendar.YEAR);
		int monthTemp = calendar.get(Calendar.MONTH);
		int dayTemp = calendar.get(Calendar.DAY_OF_MONTH);
		if (yearTemp != year || monthTemp != month || dayTemp != day){
			return;
		}
		selectYear = year;
		selectMonth = month;
		selectDay = day;
		for (ECalendar view : viewSet) {
			view.initSelect(selectYear, selectMonth, selectDay);
		}
		int position = getPosition(selectYear, selectMonth);
		pager.setCurrentItem(position, false);
		int week = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		listener.select(selectYear, selectMonth + 1, selectDay, week == 0 ? 7 : week);
	}

	public void selectMonth(int year, int month) {
		if (pager == null || year < 1970 || month < 1 || month > 12){
			return;
		}
		int position = getPosition(year, month);
		pager.setCurrentItem(position, false);
	}

	/**
	 * 设置签到记录
	 *
	 * @param signRecords 为日期格式像 "2017-08-25"
	 */
	public void setSignRecords(final HashMap<String, Boolean> signRecords) {
		if (signRecords == null) {
			return;
		}
		this.signRecords = signRecords;
		for (ECalendar view : viewSet) {
			view.setSignRecords(signRecords);
			view.invalidate();
		}
	}

	public void setNoteData(final HashMap<String, CalendarBean> data) {
		if (data == null){
			return;
		}
		this.datas = data;
		for (ECalendar view : viewSet) {
			view.setDatas(datas);
			view.invalidate();
		}
	}

	public void showNextMonth() {
		if (pager != null) {
			int index = pager.getCurrentItem() + 1;
			pager.setCurrentItem(index, true);
		}
	}

	public void showPreviousMonth() {
		if (pager != null) {
			int index = pager.getCurrentItem() - 1;
			pager.setCurrentItem(index, true);
		}
	}

	public void backToday() {
		if (pager != null) {
			ECalendar item = (ECalendar) pager.findViewWithTag(pager.getCurrentItem());
			if (item != null) {
				int[] info = item.getCurrentDayInfo();
				selectDate(info[0], info[1] + 1, info[2]);
			}
		}
	}


}
